{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "import tensorflow as tf\n",
    "from pprint import pprint\n",
    "from data_process import build_vocab, batch_iter, sentence_to_index\n",
    "from models import RNN"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# RNN Operation: $h_t=tanh(W*[x_t;h_{t-1}] + b)$\n",
    "<img src=\"https://cdn-images-1.medium.com/max/1600/1*NKhwsOYNUT5xU7Pyf6Znhg.png\">"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# RNN Operation using numpy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "batch_size = 1\n",
    "time_step = 10\n",
    "input_size = 4\n",
    "hidden_size = 3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x_input = np.random.normal(size=(batch_size, input_size))\n",
    "prev_state = np.random.normal(size=(batch_size, hidden_size))\n",
    "w = np.random.normal(size=(input_size + hidden_size, hidden_size))\n",
    "b = np.random.normal(size=(hidden_size))\n",
    "print('x_input:')\n",
    "pprint(x_input)\n",
    "print('\\nprev_state:')\n",
    "pprint(prev_state)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def RNN_numpy(x_input, previous_state, w, b):\n",
    "    x = np.concatenate((x_input, previous_state), axis=1)\n",
    "    state = np.tanh(np.add(np.matmul(x, w), b))\n",
    "    output = state\n",
    "    return output, state"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "output, state = RNN_numpy(x_input, prev_state, w, b)\n",
    "print('output:')\n",
    "pprint(output)\n",
    "print('\\nstate:')\n",
    "pprint(state)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# RNN Operation using tensorflow"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tf.reset_default_graph()\n",
    "x_input_tensor = tf.constant(x_input, dtype=tf.float32)\n",
    "prev_state_tensor = tf.constant(prev_state, dtype=tf.float32)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cell = tf.nn.rnn_cell.BasicRNNCell(hidden_size, reuse=tf.AUTO_REUSE)\n",
    "cell(x_input_tensor, prev_state_tensor)\n",
    "w_assign = tf.assign(cell.trainable_variables[0], w)\n",
    "b_assign = tf.assign(cell.trainable_variables[1], b)\n",
    "sess = tf.Session()\n",
    "sess.run([w_assign, b_assign])\n",
    "print('x_input_tensor:')\n",
    "pprint(sess.run(x_input_tensor))\n",
    "print('\\nprev_state_tensor:')\n",
    "pprint(sess.run(prev_state_tensor))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "output_tensor, state_tensor = cell(inputs=x_input_tensor, state=prev_state_tensor)\n",
    "print('output:')\n",
    "pprint(sess.run(output_tensor))\n",
    "print('\\nstate:')\n",
    "pprint(sess.run(state_tensor))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# RNN Sequence Operation using numpy "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x_seq_input = np.random.normal(size=(batch_size, time_step, input_size))\n",
    "initial_state = np.random.normal(size=(batch_size, hidden_size))\n",
    "print('x_seq_input:')\n",
    "pprint(x_seq_input)\n",
    "print('\\ninitial_state:')\n",
    "pprint(initial_state)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def seqRNN(x_input, initial_state, w, b):\n",
    "    state = initial_state\n",
    "    output = []\n",
    "    for i in range(x_input.shape[1]):\n",
    "        _, state = RNN_numpy([x_input[0][i]], state, w, b)\n",
    "        output.append(state)\n",
    "    return output, state"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "output, state = seqRNN(x_seq_input, initial_state, w ,b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('output:')\n",
    "pprint(output)\n",
    "print('\\nstate:')\n",
    "pprint(state)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# RNN Sequence Operation with tensorflow"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x_seq_input_tensor = tf.constant(x_seq_input, dtype=tf.float32)\n",
    "initial_state_tensor = tf.constant(initial_state, dtype=tf.float32)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "output, state = tf.nn.dynamic_rnn(cell, \n",
    "                                  x_seq_input_tensor, \n",
    "                                  initial_state=initial_state_tensor,\n",
    "                                  dtype=tf.float32)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('output:')\n",
    "pprint(sess.run(output))\n",
    "print('\\nstate:')\n",
    "pprint(sess.run(state))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# from text to RNN Sequence Operation with tensorflow"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data = ['나는 생각한다 고로 나는 존재한다.',\n",
    "        '모든 국가는 그에 걸맞는 국가를 가진다.',\n",
    "        '이것 또한 지나가리라',\n",
    "        '죄는 미워하되 사람은 미워하지 마라.',\n",
    "        '일찍 일어나는 새가 벌레를 잡는다']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "vocab, _, vocab_size = build_vocab(data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "seq_input = sentence_to_index(data, vocab)\n",
    "input_length = tf.reduce_sum(tf.sign(seq_input), axis=1)\n",
    "print('seq_input:')\n",
    "pprint(seq_input)\n",
    "print('\\ninput_length:')\n",
    "pprint(sess.run(input_length))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "embedding = tf.constant(np.random.normal(size=(vocab_size, input_size)), dtype=tf.float32)\n",
    "embedded_input = tf.nn.embedding_lookup(embedding, seq_input)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "output, state = tf.nn.dynamic_rnn(cell, \n",
    "                                  embedded_input, \n",
    "                                  input_length, \n",
    "                                  dtype=tf.float32)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('output:')\n",
    "pprint(sess.run(output))\n",
    "print('\\nstate:')\n",
    "pprint(sess.run(state))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Sentiment Analysis with RNN"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "train = pd.read_csv('./data/train-5T.txt', delimiter='\\t')\n",
    "test = pd.read_csv('./data/test-1T.txt', delimiter='\\t')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_train = train.document\n",
    "Y_train = train.label\n",
    "X_test = test.document\n",
    "Y_test = test.label"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "max_vocab = 50000\n",
    "vocab, _, vocab_size = build_vocab(X_train, max_vocab)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "batches = batch_iter(list(zip(X_train, Y_train)), batch_size=64, num_epochs=15)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "config = tf.ConfigProto()\n",
    "config.gpu_options.allow_growth = True\n",
    "tf.reset_default_graph()\n",
    "sess = tf.Session(config=config)\n",
    "model = RNN(sess=sess, vocab_size=vocab_size, lr=1e-2)\n",
    "train_loss = []\n",
    "train_acc = []\n",
    "test_loss = []\n",
    "test_acc = []\n",
    "\n",
    "for step, batch in enumerate(batches):\n",
    "    x_train, y_train = zip(*batch)\n",
    "    x_train = sentence_to_index(x_train, vocab)\n",
    "    acc = model.get_accuracy(x_train, y_train)\n",
    "    l, _ = model.train(x_train, y_train)\n",
    "    train_loss.append(l)\n",
    "    train_acc.append(acc)\n",
    "    \n",
    "    if step % 100 == 0:\n",
    "        test_batches = batch_iter(list(zip(X_test, Y_test)), batch_size=64, num_epochs=1)\n",
    "        for test_batch in test_batches:\n",
    "            x_test, y_test = zip(*test_batch)\n",
    "            x_test = sentence_to_index(x_test, vocab)\n",
    "            t_acc = model.get_accuracy(x_test, y_test)\n",
    "            t_loss = model.get_loss(x_test, y_test)\n",
    "            test_loss.append(t_loss)\n",
    "            test_acc.append(t_acc)\n",
    "        print('batch:', '%04d' % step, '\\ntrain loss:', '%.5f' % np.mean(train_loss), \n",
    "              '\\ttest loss:', '%.5f' % np.mean(test_loss))\n",
    "        print('train accuracy:', '%.3f' % np.mean(train_acc), '\\ttest accuracy:', \n",
    "              '%.3f' % np.mean(test_acc), '\\n')\n",
    "        train_loss = []\n",
    "        train_acc = []\n",
    "        test_loss = []\n",
    "        test_acc = []"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python tensor",
   "language": "python",
   "name": "tensor"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
